#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include <time.h>

double Max (double*, int);


int main (void){

    int i,j, count= 0, J_ORDER, J_ROW_TEST, J_ITE_MAX;
    double Mr, aux=0, J_ERROR, rowTest=0;
    double **MatrizA, **MatrizAEstrela, *VetorB, *VetorBEstrela, *VetorX_k, *VetorX_k1, *VetorDif;
    time_t startTime, endTime;

    /* Inicia a contagem do tempo */
	startTime = time(NULL);


    /*Leitura da ordem da matriz*/
    scanf("%d", &J_ORDER);

    /*Alocacao de espaco*/
    MatrizA = (double**) malloc(J_ORDER*sizeof(double*));
    MatrizAEstrela = (double**) malloc(J_ORDER*sizeof(double*));
    VetorB = (double*) malloc(J_ORDER*sizeof(double));
    VetorBEstrela = (double*) malloc(J_ORDER*sizeof(double));
    VetorX_k = (double*) malloc(J_ORDER*sizeof(double));
    VetorX_k1 = (double*) malloc(J_ORDER*sizeof(double));
    VetorDif = (double*) malloc(J_ORDER*sizeof(double));
    for(i=0; i<J_ORDER; i++){
        MatrizA[i] = (double*) malloc(J_ORDER*sizeof(double));
        MatrizAEstrela[i] = (double*) malloc(J_ORDER*sizeof(double));
    }

    /*Leitura da fila a ser avaliada*/
    scanf("%d", &J_ROW_TEST);

    /*Leitura do erro permitido*/
    scanf("%lf", &J_ERROR);

    /*Leitura do nro maximo de iteracoes permitido*/
    scanf("%d", &J_ITE_MAX);

    /*Leitura da matriz A*/
    for(i=0; i< J_ORDER; i++){
        for(j=0; j<J_ORDER; j++)
            scanf("%lf", &MatrizA[i][j]);
    }

    /*Leitura do vetor B*/
    for(i=0; i< J_ORDER; i++){
        scanf("%lf", &VetorB[i]);
    }


    /*Cálculo da Matriz AEstrela*/
    for(i=0; i<J_ORDER; i++){
        for(j=0; j<J_ORDER; j++){
            if(i != j)
                MatrizAEstrela[i][j] = MatrizA[i][j]/MatrizA[i][i];
            else
                MatrizAEstrela[i][j] = 0;
        }
    }

    /*Cálculo do Vetor BEstrela*/
    for(i=0; i<J_ORDER; i++){
        VetorBEstrela[i] = VetorB[i]/MatrizA[i][i];
    }

    /*Cálculo do Vetor X*/
    for(i=0; i<J_ORDER; i++){
        VetorX_k[i] = VetorBEstrela[i];
    }

    do{
        /*Cálculo de X k+1*/
        for(i=0; i<J_ORDER; i++){
            for(j=0; j<J_ORDER; j++){
                if(i!=j){
                    aux += MatrizAEstrela[i][j]*VetorX_k[j];
                }
            }
            VetorX_k1[i] = VetorBEstrela[i] - aux;
            aux = 0;
        }

        /*Cálculo da Diferenca entre os valores de k e k+1*/
        for(i=0; i<J_ORDER; i++){
            VetorDif[i] = fabs(VetorX_k1[i]-VetorX_k[i]);
        }
        Mr = Max(VetorDif,J_ORDER)/Max(VetorX_k1,J_ORDER);

        /*Atualizacao do Vetor de X k por X k+1*/
        for(i=0; i<J_ORDER; i++){
            VetorX_k[i] = VetorX_k1[i];
        }

        count++;
    }while(count<J_ITE_MAX && Mr>J_ERROR);

    /*Row Test*/
    for(j=0; j<J_ORDER; j++){
        rowTest += MatrizA[J_ROW_TEST][j]*VetorX_k1[j];
    }

    /*Encerra a contagem do tempo*/
	endTime = time(NULL);

	printf("Tempo de execução: %.1lf segundos\n", difftime (endTime,startTime));
    printf("Interations: %d\n",count);
    printf("RowTest: %d => [%lf] =? %lf\n", J_ROW_TEST, rowTest, VetorB[J_ROW_TEST]);

}

/*Funcao para calcular o valor máximo de um vetor*/
double Max (double Vetor[], int J_ORDER){
    int i;
    double max;

    max = fabs(Vetor[0]);

    for(i=1; i<J_ORDER; i++){
        if(fabs(Vetor[i])>max)
            max = fabs(Vetor[i]);
    }
return max;
}